<?php
/**
 * Created by PhpStorm.
 * User: Drunk
 * Date: 2017-2-15
 * Time: 16:39
 */

namespace drunk;

class request{
    private $_response,
        $_handle,
        $_options;

    /**
     * 远程请求
     * request constructor.
     * @param array $options curl请求配置
     */
    function __construct($options = null) {
        $this->_handle = curl_init();
        $this->_options = [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
        ];
        if (is_array($options)) $this->_options = $options + $this->_options;
        curl_setopt_array($this->_handle, $this->_options);
    }

    /**
     * 设置请求参数
     * @param int|array $key
     * @param mixed $value
     * @return $this
     */
    public function set_option($key, $value = null){
        $options = is_array($key) ? $key : [$key => $value];
        curl_setopt_array($this->_handle, $options);
        return $this;
    }

    /**
     * 发送请求取返回数据, 若响应不正常则返回假
     * @param string $url
     * @param array|string $post_data 若非假, 则发送post请求, 若为数组或字符串, 则作为post数据发送
     * @return bool|mixed
     */
    public function send($url, $post_data = null){
        curl_setopt($this->_handle, CURLOPT_URL, $url);
        if ($post_data) {
            curl_setopt($this->_handle, CURLOPT_POST, true);
            if (is_array($post_data) || is_string($post_data)) curl_setopt($this->_handle, CURLOPT_POSTFIELDS, $post_data);
        }
        $content = curl_exec($this->_handle);
        $this->_response = curl_getinfo($this->_handle);
        $this->_response['content_type'] = (new \finfo)->buffer($content, FILEINFO_MIME_TYPE); // 来啊, 看爹能取到不, 艹!
        if ($this->_response['http_code'] != 200) return false;
        return $content;
    }

    /**
     * 发送请求并将返回数据存为文件
     * @param string $path 若为目录, 则自动生成文件名保存, 若为空, 则返回失败
     * @param string $url
     * @param array|string $post_data
     * @return bool
     */
    public function send_save($path, $url, $post_data = null){
        if (is_dir($path)) $path = $path . '/' . uniqid('', true);
        if (empty($path)) return false;
        $content = $this->send($url, $post_data);
        return file::write($path, $content);
    }

    /**
     * 取请求响应信息
     * @param string $option
     * @return mixed
     */
    public function response($option = null){
        return empty($option) ? $this->_response : $this->_response[$option];
    }

    /**
     * 析构关闭curl
     */
    function __destruct() {
        curl_close($this->_handle); // 关闭请求句柄
    }

    /**
     * 发送get请求并取返回数据
     * @param string $url
     * @return bool|mixed
     */
    public static function send_get($url){
        return (new request)->send($url);
    }

    /**
     * 发送post请求并取返回数据
     * @param string $url
     * @param string|array|bool $post_data
     * @return bool|mixed
     */
    public static function send_post($url, $post_data = true){
        return (new request)->send($url, $post_data);
    }


    /**
     * 请求配置初始化
     */
    public static function init(){
        session_start();
    }

    /**
     * 取get请求参数
     * @param string $key
     * @param string $type
     * @param null $if_null
     * @return bool|null
     */
    public static function get($key = null, $type = null, $if_null = null, $trim = true){
        return self::take($key, $type, $if_null, $trim, 'get');
    }

    public static function post($key = null, $type = null, $if_null = null, $trim = true){
        return self::take($key, $type, $if_null, $trim, 'post');
    }

    /**
     * @param null $key
     * @param null $type null // [int, float, bool]
     * @param null $if_null
     * @param string $request_type
     * @return bool|null
     */
    public static function take($key = null, $type = null, $if_null = null, $trim = true, $request_type = 'request'){
        $request_type = strtolower($request_type);
        $data = $request_type === 'post' ? $_POST : ($request_type === 'get' ? $_GET : $_REQUEST);
        if (is_null($key)) return $data;
        if (!isset($data[$key])) return $if_null;
        $argument = $data[$key];
        if ($trim && is_string($argument)) $argument = trim($argument);
        if (is_null($type)) return $argument;
        $type = strtolower($type);
        $map = [
            'str' => 'strval',
            'int' => 'intval',
            'float' => 'floatval',
        ];
        if ($type === 'bool'){
            $argument = !empty($argument);
        } else if(array_key_exists($type, $map)) {
            $argument = $map[$type]($argument);
        }
        return $argument;
    }


    /**
     * 获取客户端IP地址
     * @param bool   $long {0:返回IP地址, 1:返回IPV4地址数字}
     * @return mixed
     */
    public static function ip($long = false) {
        $type      = $long ? 1 : 0;
        static $ip = null;
        if (null !== $ip) return $ip[$type];

        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown', $arr);
            if (false !== $pos) unset($arr[$pos]);
            $ip = trim(current($arr));
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }

        // IP地址合法验证
        $long = sprintf("%u", ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }

    public static function session_set($key, $value){
        return $_SESSION[$key] = $value;
    }

    public static function session_get($key){
        return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : null;
    }

    public static function session_delete($key){
        if (is_null($key)) session_unset();
        unset($_SESSION[$key]);
        return true;
    }

    public static function cookie_set($key, $value){
//
    }

    public static function cookie_get($key){
//
    }

    public static function cookie_delete($key){
//
    }

    /**
     * 取请求需响应的数据类型
     * @return bool|null|string
     */
    public static function data_type(){
        static $data_type,
        $data_type_map = [ // 允许响应的数据类型表
            'html' => 1,
            'json' => 1,
            'jsonp' => 1,
            'xml' => 1,
        ];
        if (!is_null($data_type)) return $data_type;
        $data_type = self::get('response_data_type', 'str');
        if (!empty($data_type) // 尝试获取url响应数据类型设置
            && array_key_exists(strtolower($data_type), $data_type_map))
            return $data_type;
        $node = \dce\node::current();
        if (!empty($node['data_type']) // 尝试获取节点响应数据类型
            && ($data_type = $node['data_type'])
            && array_key_exists(strtolower($data_type), $data_type_map))
            return $data_type;
        $data_type = self::is_ajax()
            ? 'json'
            : (php_sapi_name() === 'cli' ? 'cli' : 'html'); // 是否命令行界面
        return $data_type;
    }

    /**
     * 判断是否ajax请求
     * @return bool
     */
    public static function is_ajax(){
        return isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower($_SERVER["HTTP_X_REQUESTED_WITH"])=="xmlhttprequest";
    }
}